1 module hip.graphics.g2d.renderer2d; 2 3 version(Have_bindbc_lua) version = HipremeEngineLua; 4 5 import hip.graphics.g2d.spritebatch; 6 import hip.graphics.g2d.tilemap; 7 import hip.graphics.g2d.geometrybatch; 8 import hip.graphics.orthocamera; 9 import hip.hiprenderer; 10 import hip.bind.interpreters; 11 public import hip.api.graphics.color; 12 public import hip.graphics.g2d.textrenderer; 13 public import hip.api.renderer.viewport; 14 15 public import hip.api.data.font; 16 17 package __gshared 18 { 19 IHipTexture defaultTexture; 20 HipSpriteBatch spBatch; 21 GeometryBatch geoBatch; 22 HipTextRenderer textBatch; 23 HipOrthoCamera camera; 24 Viewport viewport; 25 HipTextRenderer textRenderer; 26 IHipBatch lastBatch; 27 bool autoUpdateCameraAndViewport; 28 float sharedDepth = 0; 29 } 30 31 void manageBatchChange(IHipBatch newBatch) 32 { 33 if(lastBatch !is null && lastBatch !is newBatch) 34 { 35 sharedDepth+= 0.1; 36 lastBatch.draw(); 37 38 if(newBatch !is null) 39 newBatch.setCurrentDepth(sharedDepth); 40 } 41 lastBatch = newBatch; 42 } 43 44 45 import hip.console.log; 46 void initialize(HipInterpreterEntry entry = HipInterpreterEntry.init, bool shouldAutoUpdateCameraAndViewport = true) 47 { 48 autoUpdateCameraAndViewport = shouldAutoUpdateCameraAndViewport; 49 hiplog("2D Renderer: Initializing viewport"); 50 viewport = new Viewport(0, 0, HipRenderer.width, HipRenderer.height); 51 viewport.setWorldSize(HipRenderer.width, HipRenderer.height); 52 viewport.setType(ViewportType.fit, HipRenderer.width, HipRenderer.height); 53 HipRenderer.setViewport(viewport); 54 hiplog("2D Renderer: Initializing camera"); 55 camera = new HipOrthoCamera(); 56 camera.setSize(viewport.worldWidth, viewport.worldHeight); 57 58 hiplog("2D Renderer: Initializing text renderer"); 59 textBatch = new HipTextRenderer(camera); 60 hiplog("2D Renderer: Initializing geometrybatch"); 61 geoBatch = new GeometryBatch(camera); 62 hiplog("2D Renderer: Initializing spritebatch"); 63 spBatch = new HipSpriteBatch(camera); 64 // setGeometryColor(HipColor.white); 65 66 67 version(HipremeEngineLua) 68 { 69 hiplog("2D Renderer: sending lua functions"); 70 if(entry != HipInterpreterEntry.init) 71 { 72 sendInterpreterFunc!(setGeometryColor)(entry.intepreter); 73 sendInterpreterFunc!(drawPixel)(entry.intepreter); 74 sendInterpreterFunc!(drawRectangle)(entry.intepreter); 75 sendInterpreterFunc!(drawTriangle)(entry.intepreter); 76 sendInterpreterFunc!(fillRectangle)(entry.intepreter); 77 sendInterpreterFunc!(fillEllipse)(entry.intepreter); 78 sendInterpreterFunc!(drawEllipse)(entry.intepreter); 79 sendInterpreterFunc!(fillTriangle)(entry.intepreter); 80 sendInterpreterFunc!(drawLine)(entry.intepreter); 81 sendInterpreterFunc!(drawQuadraticBezierLine)(entry.intepreter); 82 // sendInterpreterFunc!(drawText)(entry.intepreter); not supported yet 83 } 84 } 85 86 } 87 88 /** 89 * This resizes both the 2D renderer viewport and its Orthographic Camera, maintaining always the 90 * correct aspect ratio 91 */ 92 void resizeRenderer2D(uint width, uint height) 93 { 94 if(autoUpdateCameraAndViewport) 95 { 96 if(viewport !is null && HipRenderer.getCurrentViewport() == viewport) 97 HipRenderer.setViewport(viewport); 98 if(camera !is null) 99 camera.setSize(viewport.worldWidth, viewport.worldHeight); 100 } 101 } 102 103 //TODO: Find a way to remove export from release 104 export extern(System): 105 106 107 int[2] getWindowSize(){return [HipRenderer.width, HipRenderer.height];} 108 109 void setWindowSize(uint width, uint height) 110 { 111 HipRenderer.setWindowSize(width, height); 112 HipRenderer.setViewport(viewport); 113 camera.setSize(cast(int)viewport.worldWidth,cast(int)viewport.worldHeight); 114 } 115 void setCameraSize(uint width, uint height){camera.setSize(width, height);} 116 void setViewport(Viewport v) 117 { 118 HipRenderer.setViewport(v); 119 } 120 void setStencilTestingEnabled(bool bEnable) 121 { 122 manageBatchChange(null); 123 HipRenderer.setStencilTestingEnabled(bEnable); 124 } 125 void setStencilTestingMask(uint mask) 126 { 127 manageBatchChange(null); 128 HipRenderer.setStencilTestingMask(mask); 129 } 130 void setRendererColorMask(ubyte r, ubyte g, ubyte b, ubyte a) 131 { 132 manageBatchChange(null); 133 HipRenderer.setColorMask(r,g,b,a); 134 } 135 void setStencilTestingFunction(HipStencilTestingFunction passFunc, uint reference, uint mask) 136 { 137 manageBatchChange(null); 138 HipRenderer.setStencilTestingFunction(passFunc, reference, mask); 139 } 140 void setStencilOperation(HipStencilOperation stencilFail, HipStencilOperation depthFail, HipStencilOperation stencilAndDephPass) 141 { 142 manageBatchChange(null); 143 HipRenderer.setStencilOperation(stencilFail, depthFail, stencilAndDephPass); 144 } 145 Viewport getCurrentViewport() 146 { 147 return HipRenderer.getCurrentViewport(); 148 } 149 150 void setRendererErrorCheckingEnabled(bool enable) 151 { 152 HipRenderer.setErrorCheckingEnabled(enable); 153 } 154 void setGeometryColor(const HipColor color){geoBatch.setColor(color);} 155 void drawPixel(int x, int y, HipColor color = HipColor.no) 156 { 157 manageBatchChange(geoBatch); 158 geoBatch.drawPixel(x, y,color); 159 } 160 void drawRectangle(int x, int y, int w, int h, HipColor color = HipColor.no) 161 { 162 manageBatchChange(geoBatch); 163 geoBatch.drawRectangle(x,y,w,h,color); 164 } 165 void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, HipColor color = HipColor.no) 166 { 167 manageBatchChange(geoBatch); 168 geoBatch.drawTriangle(x1,y1,x2,y2,x3,y3,color); 169 } 170 void drawEllipse(int x, int y, int radiusW, int radiusH, int degrees = 360, HipColor color = HipColor.no, int precision = 24) 171 { 172 manageBatchChange(geoBatch); 173 geoBatch.drawEllipse(x,y,radiusW,radiusH,degrees,color,precision); 174 } 175 void drawLine(int x1, int y1, int x2, int y2, HipColor color = HipColor.no) 176 { 177 manageBatchChange(geoBatch); 178 geoBatch.drawLine(x1,y1,x2,y2,color); 179 } 180 void drawQuadraticBezierLine(int x0, int y0, int x1, int y1, int x2, int y2, int precision=24, HipColor color = HipColor.no) 181 { 182 manageBatchChange(geoBatch); 183 geoBatch.drawQuadraticBezierLine(x0,y0,x1,y1,x2,y2,precision,color); 184 } 185 void fillRectangle(int x, int y, int w, int h, HipColor color = HipColor.no) 186 { 187 manageBatchChange(geoBatch); 188 geoBatch.fillRectangle(x,y,w,h,color); 189 } 190 void fillRoundRect(int x, int y, int w, int h, int radius = 4, HipColor color = HipColor.no, int precision = 16) 191 { 192 manageBatchChange(geoBatch); 193 geoBatch.fillRoundRect(x,y,w,h,radius, color, precision); 194 } 195 void fillEllipse(int x, int y, int radiusW, int radiusH = -1, int degrees = 360, HipColor color = HipColor.no, int precision = 24) 196 { 197 manageBatchChange(geoBatch); 198 geoBatch.fillEllipse(x,y,radiusW,radiusH,degrees,color,precision); 199 } 200 void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, HipColor color = HipColor.no) 201 { 202 manageBatchChange(geoBatch); 203 geoBatch.fillTriangle(x1,y1,x2,y2,x3,y3,color); 204 } 205 206 void drawSprite(IHipTexture texture, ubyte[] vertices) 207 { 208 manageBatchChange(spBatch); 209 spBatch.draw(texture, vertices); 210 } 211 void drawRegion(IHipTextureRegion reg, int x, int y, int z = 0, const HipColor color = HipColor.white, float scaleX = 1, float scaleY = 1, float rotation = 0) 212 { 213 manageBatchChange(spBatch); 214 spBatch.draw(reg, x, y, z, color, scaleX, scaleY, rotation); 215 } 216 void drawMap(IHipTilemap map) 217 { 218 manageBatchChange(spBatch); 219 map.render(spBatch, false); 220 } 221 222 void drawTexture(IHipTexture texture, int x, int y, int z = 0, const HipColor color = HipColor.white, float scaleX = 1, float scaleY = 1, float rotation = 0) 223 { 224 manageBatchChange(spBatch); 225 spBatch.draw(texture, x, y, z, color, scaleX, scaleY, rotation); 226 } 227 228 229 public import hip.util.data_structures : Array2D, Array2D_GC; 230 Array2D_GC!IHipTextureRegion cropSpritesheet( 231 IHipTexture t, 232 uint frameWidth, uint frameHeight, 233 uint width, uint height, 234 uint offsetX, uint offsetY, 235 uint offsetXPerFrame, uint offsetYPerFrame 236 ) 237 { 238 import hip.assets.texture; 239 import hip.util.lifetime; 240 return cast(typeof(return))hipSaveRef(HipTextureRegion.cropSpritesheet(t, 241 frameWidth, frameHeight, 242 width, height, 243 offsetX, offsetY, 244 offsetXPerFrame, offsetYPerFrame 245 ).toGC()); 246 } 247 248 void setFont(IHipFont font) 249 { 250 import hip.global.gamedef; 251 if(font is null) 252 textBatch.setFont(cast(IHipFont)HipDefaultAssets.font); 253 else 254 textBatch.setFont(font); 255 } 256 257 void setTextColor(HipColor color) 258 { 259 manageBatchChange(textBatch); 260 textBatch.setColor(color); 261 } 262 void drawText(string text, int x, int y, float scale = 1.0f, HipColor color = HipColor.white, HipTextAlign align_ = HipTextAlign.centerLeft, 263 Size bounds = Size.init, bool wordWrap = false) 264 { 265 manageBatchChange(textBatch); 266 textBatch.setColor(color); 267 textBatch.draw(text, x, y, scale, align_, bounds, wordWrap); 268 } 269 270 void drawTextVertices(void[] vertices, IHipFont font) 271 { 272 manageBatchChange(textBatch); 273 textBatch.addVertices(vertices, font); 274 } 275 276 Array2D_GC!IHipTextureRegion cropSpritesheetRowsAndColumns(IHipTexture t, uint rows, uint columns) 277 { 278 uint frameWidth = t.getWidth() / columns; 279 uint frameHeight = t.getHeight() / rows; 280 return cropSpritesheet(t,frameWidth,frameHeight, t.getWidth, t.getHeight, 0, 0, 0, 0); 281 } 282 283 void finishRender2D() 284 { 285 if(geoBatch) geoBatch.flush(); 286 if(spBatch) spBatch.flush(); 287 if(textBatch) textBatch.flush(); 288 lastBatch = null; 289 sharedDepth = 0; 290 if(geoBatch) geoBatch.setCurrentDepth(0); 291 if(spBatch) spBatch.setCurrentDepth(0); 292 if(textBatch) textBatch.setCurrentDepth(0); 293 } 294 295 void drawGCStats(int x = 0, int y = -1) 296 { 297 import hip.graphics.g2d.profiling; 298 hip.graphics.g2d.profiling.drawGCStats(x, y); 299 } 300 301 void drawTimings(int x = -1, int y = 0, bool clearTimings = false) 302 { 303 import hip.graphics.g2d.profiling; 304 hip.graphics.g2d.profiling.drawTimings(x, y, clearTimings); 305 } 306 307 version(Standalone) 308 { 309 public import exportd; 310 }